package com.naiterui.common.redis;

public class RedisLock {
    String lockKey;
    int expireMsecs;
    int timeoutMsecs;
    boolean locked;

    public RedisLock(String lockKey) {
        this.expireMsecs = 60000;
        this.timeoutMsecs = 10000;
        this.locked = false;
        this.lockKey = lockKey;
    }

    public RedisLock(String lockKey, int timeoutMsecs) {
        this(lockKey);
        this.timeoutMsecs = timeoutMsecs;
    }

    public RedisLock(String lockKey, int timeoutMsecs, int expireMsecs) {
        this(lockKey, timeoutMsecs);
        this.expireMsecs = expireMsecs;
    }

    public String getLockKey() {
        return this.lockKey;
    }

    public synchronized boolean acquire() throws InterruptedException {
        int timeout = this.timeoutMsecs;

        while (timeout >= 0) {
            long expires = System.currentTimeMillis() + (long) this.expireMsecs + 1L;
            String expiresStr = String.valueOf(expires);  //锁到期时间
            if (RedisUtil.valueOps().setNx(this.lockKey, expiresStr) == 1L) {
                this.locked = true;
                return true;
            }
            String currentValueStr = RedisUtil.valueOps().getString(this.lockKey);
            if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) {
                String oldValueStr = RedisUtil.keyOps().getSet(this.lockKey, expiresStr);
                if (oldValueStr != null && oldValueStr.equals(currentValueStr)) {
                    this.locked = true;
                    return true;
                }
            }

            timeout -= 300;
            Thread.sleep(300L);
        }

        return false;
    }

    public synchronized void release() {
        if (this.locked) {
            RedisUtil.keyOps().delete(this.lockKey);
            this.locked = false;
        }
    }
}
